// stores/utils/persist.ts
import { PiniaPluginContext } from 'pinia'

export interface StorePersistOptions {
	key ?: string // 自定义存储键名
	// 移除 storage 选项，默认仅使用 local
	paths ?: string[] // 指定要持久化的状态路径
}

// 扩展 Pinia 的 Store 类型，支持 persist 选项
declare module 'pinia' {
	interface DefineStoreOptionsBase<S, Store> {
		persist ?: StorePersistOptions | boolean; // 支持 boolean 类型
	}
}

export function createPersistedState(globalOptions ?: StorePersistOptions) {
	return (context : PiniaPluginContext) => {
		const { store } = context;

		const localPersist = context.options.persist;
		const localOptions = typeof localPersist === 'boolean'
			? {}
			: (localPersist || {});

		// 合并配置（局部覆盖全局）
		const options = {
			...globalOptions,
			...localOptions
		};

		// 从配置中提取参数（仅保留 local 存储相关）
		const { key = store.$id, paths } = options;
		const storageKey = `pinia-${key}`;

		// 从 local 存储中恢复数据（仅使用 localStorage）
		const data = uni.getStorageSync(storageKey);
		if (data) {
			try {
				const parsedData = JSON.parse(data);
				if (paths && paths.length > 0) {
					const partialState : any = {};
					paths.forEach(path => {
						const value = getValueByPath(parsedData, path);
						if (value !== undefined) {
							setValueByPath(partialState, path, value);
						}
					});
					store.$patch(partialState);
				} else {
					store.$patch(parsedData);
				}
			} catch (error) {
				console.error(`Failed to parse persisted state for ${store.$id}:`, error);
			}
		}

		// 监听状态变化并持久化到 local 存储
		store.$subscribe((mutation, state) => {
			let dataToSave = state;
			if (paths && paths.length > 0) {
				dataToSave = {};
				paths.forEach(path => {
					const value = getValueByPath(state, path);
					if (value !== undefined) {
						setValueByPath(dataToSave, path, value);
					}
				});
			}

			try {
				// 仅使用 localStorage 同步存储
				uni.setStorageSync(storageKey, JSON.stringify(dataToSave));
			} catch (error) {
				console.error(`Failed to persist state for ${store.$id}:`, error);
			}
		});
	}
}


function getValueByPath(obj : any, path : string) {
	return path.split('.').reduce((acc, part) => acc && acc[part], obj);
}

function setValueByPath(obj : any, path : string, value : any) {
	const parts = path.split('.');
	const last = parts.pop();
	let current = obj;

	for (const part of parts) {
		if (!current[part]) {
			current[part] = {};
		}
		current = current[part];
	}

	if (last) {
		current[last] = value;
	}
}